//---------------------------------------------------------------------------
//jWebSocket - Copyright (c) 2010 Innotrade GmbH
//---------------------------------------------------------------------------
//This program is free software; you can redistribute it and/or modify it
//under the terms of the GNU Lesser General Public License as published by the
//Free Software Foundation; either version 3 of the License, or (at your
//option) any later version.
//This program is distributed in the hope that it will be useful, but WITHOUT
//ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
//FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
//for more details.
//You should have received a copy of the GNU Lesser General Public License
//along with this program; if not, see <http://www.gnu.org/licenses/lgpl.html>.
//---------------------------------------------------------------------------
package com.mapmymotion;

import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.widget.ArrayAdapter;
import android.widget.Toast;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javolution.util.FastList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.jwebsocket.api.WebSocketClientEvent;
import org.jwebsocket.api.WebSocketClientTokenListener;
import org.jwebsocket.api.WebSocketConnector;
import org.jwebsocket.api.WebSocketPacket;
import org.jwebsocket.client.token.BaseTokenClient;
import org.jwebsocket.factory.JWebSocketFactory;
import org.jwebsocket.kit.RawPacket;
import org.jwebsocket.kit.WebSocketException;
import org.jwebsocket.kit.WebSocketSession;
import org.jwebsocket.server.TokenServer;
import org.jwebsocket.token.Token;

//import org.jwebsocket.token.TokenFactory;

/**
 * 
 * @author aschulze
 */
public class JWC {

	private final static int MT_OPENED = 0;
	private final static int MT_PACKET = 1;
	private final static int MT_CLOSED = 2;
	private final static int MT_TOKEN = 3;

	private final static String CONFIG_FILE = "jWebSocket";
	// private static String URL = "ws://jwebsocket.org:8787";
	private static String URL = "ws://74.50.115.240:8787";
	private static BaseTokenClient jwc;
	private static List<WebSocketClientTokenListener> listeners = new FastList<WebSocketClientTokenListener>();
	private static String DEF_ENCODING = "UTF-8";
	protected static JSONArray jArray = null;
	protected static JSONArray jArrayIntervals = null;
	protected static JSONArray jArrayPoints = null;
	protected static JSONArray jArrayFriends = null;

	// protected static boolean isClosed=true;

	public static WebSocketConnector getConnectorForUsername(String username,
			TokenServer server) {
		Map<String, WebSocketConnector> connectorMap = server
				.getAllConnectors();
		Collection<WebSocketConnector> connectors = connectorMap.values();
		for (WebSocketConnector connector : connectors) {
			if (username.equals(connector.getUsername()))
				return connector;
		}
		return null;
	}

	public static void sendaMessage(String amessage, String manymessages)
			throws WebSocketException {

		// TokenServer tokenServer = (TokenServer)
		// JWebSocketFactory.getServer("ts0");
		// WebSocketConnector connector =
		// getConnectorForUsername("rbarnes23",tokenServer);
		// Socket socket = jwc.getConnectionSocket();
		// String senderIP = socket.getInetAddress().getHostAddress();
		// String senderPort = "" + socket.getPort();

		Token lToken;
		lToken = new Token();
		lToken.setString("data", amessage);
		lToken.setString("sender", jwc.getClientId());
		lToken.setNS("org.jWebSocket.plugins.samples");
		lToken.setBoolean("responseRequested", false);
		// lToken.setType("processComplexObject");
		lToken.setType("message");
		lToken.setString("InsertActivities", manymessages);
		// lToken.setString("targetId", connector.getId());
		jwc.sendToken(lToken);
	}

	public static void getMemberId(String aemailaddress)
			throws WebSocketException {

		// TokenServer tokenServer = (TokenServer)
		// JWebSocketFactory.getServer("ts0");
		// WebSocketConnector connector =
		// getConnectorForUsername("rbarnes23",tokenServer);
		// Socket socket = jwc.getConnectionSocket();
		// String senderIP = socket.getInetAddress().getHostAddress();
		// String senderPort = "" + socket.getPort();

		Token lToken;
		lToken = new Token();
		lToken.setString("email", aemailaddress);
		lToken.setString("sender", jwc.getClientId());
		lToken.setNS("org.jWebSocket.plugins.samples");
		lToken.setBoolean("responseRequested", true);
		lToken.setType("processMemberId");
		lToken.setString("type", "processMemberId");
		// lToken.setString("targetId", connector.getId());
		jwc.sendToken(lToken);
	}

	public static void getFriends(String aId, String aAcceptedoption)
			throws WebSocketException {
		Token lToken;
		lToken = new Token();
		lToken.setString("memberid", aId);
		lToken.setString("acceptedoption", aAcceptedoption);
		lToken.setString("sender", jwc.getClientId());
		lToken.setNS("org.jWebSocket.plugins.samples");
		lToken.setBoolean("responseRequested", true);
		lToken.setType("processFriends");
		lToken.setString("type", "processFriends");
		jwc.sendToken(lToken);
	}

	public static void getActivities(String aId, String aFriends)
			throws WebSocketException {

		Token lToken;
		lToken = new Token();
		lToken.setString("memberid", aId);
		lToken.setString("friends", aFriends);
		lToken.setString("sender", jwc.getClientId());
		lToken.setNS("org.jWebSocket.plugins.samples");
		lToken.setBoolean("responseRequested", true);
		lToken.setType("processActivities");
		lToken.setString("type", "processActivities");
		jwc.sendToken(lToken);
	}

	public static void getIntervals(Integer aId) throws WebSocketException {

		Token lToken;
		lToken = new Token();
		lToken.setString("activitysummaryid", aId.toString());
		lToken.setString("sender", jwc.getClientId());
		lToken.setNS("org.jWebSocket.plugins.samples");
		lToken.setBoolean("responseRequested", true);
		lToken.setType("processIntervals");
		lToken.setString("type", "processIntervals");
		jwc.sendToken(lToken);
	}

	public static void getPoints(Integer aId) throws WebSocketException {

		Token lToken;
		lToken = new Token();
		lToken.setString("activitysummaryid", aId.toString());
		lToken.setString("sender", jwc.getClientId());
		lToken.setNS("org.jWebSocket.plugins.samples");
		lToken.setBoolean("responseRequested", true);
		lToken.setType("processPoints");
		lToken.setString("type", "processPoints");
		jwc.sendToken(lToken);
	}

	public static boolean isConnected() {
		return jwc.isConnected();
	}

	public static void init() {
		jwc = new BaseTokenClient();
		jwc.addListener(new Listener());
	}

	public static void loadSettings(Activity aActivity) {
		Properties lProps = new Properties();
		try {
			lProps.load(aActivity.openFileInput(CONFIG_FILE));
		} catch (Exception ex) {
			Toast.makeText(aActivity.getApplicationContext(),
					ex.getClass().getSimpleName() + ":" + ex.getMessage(),
					Toast.LENGTH_SHORT).show();
		}
		// URL = (String) lProps.getProperty("url",
		// "http://jwebsocket.org:8787/");
		URL = (String) lProps.getProperty("url", "http://74.50.115.240:8787/");
	}

	public static void saveSettings(Activity aActivity) {
		Properties lProps = new Properties();
		try {
			lProps.put("url", URL);
			lProps.save(
					aActivity.openFileOutput(CONFIG_FILE, Context.MODE_PRIVATE),
					"jWebSocketClient Configuration");
		} catch (Exception ex) {
			Toast.makeText(aActivity.getApplicationContext(),
					ex.getClass().getSimpleName() + ":" + ex.getMessage(),
					Toast.LENGTH_SHORT).show();
		}
	}

	public static void open() throws WebSocketException {
		jwc.open(URL);
		try {
			jwc.login("mapmymotion23", "");
			// isClosed=false;
		} catch (WebSocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			// isClosed=true;
		}
	}

	public static void close() throws WebSocketException {
		jwc.close();
		// isClosed=true;
	}

	public static void send(String aString) throws WebSocketException {
		jwc.send(URL, DEF_ENCODING);
	}

	public static void sendToken(Token aToken) throws WebSocketException {
		jwc.sendToken(aToken);
	}

	public static void sendText(String aTarget, String aData)
			throws WebSocketException {
		jwc.sendText(aTarget, aData);

	}

	public static void broadcastText(String aData) throws WebSocketException {
		jwc.broadcastText(aData);
	}

	public static void saveFile(byte[] aData, String aFilename, String aScope,
			Boolean aNotify) throws WebSocketException {
		jwc.saveFile(aData, aFilename, aScope, aNotify);
	}

	public static void addListener(WebSocketClientTokenListener aListener) {
		listeners.add(aListener);
	}

	public static void removeListener(WebSocketClientTokenListener aListener) {
		listeners.remove(aListener);
	}

	private static Handler messageHandler = new Handler() {

		@Override
		public void handleMessage(Message message) {

			switch (message.what) {
			case MT_OPENED:
				notifyOpened(null);
				break;
			case MT_PACKET:
				notifyPacket(null, (RawPacket) message.obj);
				break;
			case MT_TOKEN:
				notifyToken(null, (Token) message.obj);
				break;
			case MT_CLOSED:
				notifyClosed(null);
				break;
			}
		}
	};

	public static void notifyOpened(WebSocketClientEvent aEvent) {
		for (WebSocketClientTokenListener lListener : listeners) {
			lListener.processOpened(aEvent);
		}
	}

	public static void notifyPacket(WebSocketClientEvent aEvent,
			WebSocketPacket aPacket) {
		for (WebSocketClientTokenListener lListener : listeners) {
			lListener.processPacket(aEvent, aPacket);
		}
	}

	public static void notifyToken(WebSocketClientEvent aEvent, Token aToken) {
		for (WebSocketClientTokenListener lListener : listeners) {
			lListener.processToken(aEvent, aToken);

		}
	}

	public static void notifyClosed(WebSocketClientEvent aEvent) {
		for (WebSocketClientTokenListener lListener : listeners) {
			lListener.processClosed(aEvent);
			// isClosed=true;
		}
	}

	/**
	 * @return the URL
	 */
	public static String getURL() {
		return URL;
	}

	/**
	 * @param aURL
	 *            the URL to set
	 */
	public static void setURL(String aURL) {
		URL = aURL;
	}

	static class Listener implements WebSocketClientTokenListener {

		public void processOpened(WebSocketClientEvent aEvent) {
			Message lMsg = new Message();
			lMsg.what = MT_OPENED;
			messageHandler.sendMessage(lMsg);
		}

		public void processPacket(WebSocketClientEvent aEvent,
				WebSocketPacket aPacket) {
			Message lMsg = new Message();
			lMsg.what = MT_PACKET;
			lMsg.obj = aPacket;
			messageHandler.sendMessage(lMsg);
		}

		public void processToken(WebSocketClientEvent aEvent, Token aToken) {
			// get the type of the token
			// the type can be associated with a "command"
			String lType = aToken.getString("reqType");

			// get the namespace of the token
			// each plug-in should have its own unique namespace
			String lNS = aToken.getNS();

			// check if token has a type and a matching namespace
			if (lType != null && lNS != null) {
				if (lType.equals("processMemberId")) {
					// simply echo the complex object
					String memberid = aToken.getString("data");
					AppSettings
							.setMemberid(mainActivity.getContext(), memberid);
				}
				if (lType.equals("processActivities")) {
					// Get the latest activities
					String activitiesdata = aToken.getString("data");
					try {
						jArray = new JSONArray(activitiesdata);

					} catch (JSONException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if (lType.equals("processIntervals")) {
					// Get the latest activity Intervals
					jArrayIntervals = null;
					String pointsdata = aToken.getString("data");
					try {
						jArrayIntervals = new JSONArray(pointsdata);

					} catch (JSONException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if (lType.equals("processFriends")) {
					// Get the latest activity Intervals
					jArrayFriends = null;
					String friendsdata = aToken.getString("data");
					try {
						jArrayFriends = new JSONArray(friendsdata);

					} catch (JSONException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if (lType.equals("processPoints")) {
					// Get the latest Points Intervals
					jArrayPoints = null;
					String pointsdata = aToken.getString("data");
					try {
						jArrayPoints = new JSONArray(pointsdata);

					} catch (JSONException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}

			}
			Message lMsg = new Message();
			lMsg.what = MT_TOKEN;
			lMsg.obj = aToken;
			messageHandler.sendMessage(lMsg);
		}

		public void processClosed(WebSocketClientEvent aEvent) {
			Message lMsg = new Message();
			lMsg.what = MT_CLOSED;
			messageHandler.sendMessage(lMsg);
		}
	}

	public static JSONArray getActivities() {
		return jArray;
	}

	public static JSONArray getFriends() {
		return jArrayFriends;
	}

	public static JSONArray getIntervals() {
		return jArrayIntervals;
	}
	public static JSONArray getPoints() {
		return jArrayPoints;
	}

}